#ifndef __config_dkfjiwoo3w3yy82389__
#define __config_dkfjiwoo3w3yy82389__

#include <cstdio>

#include <hude/base/base_type.hpp>
#include <hude/base/log.hpp>
#include <hude/utils/json.hpp>

namespace hude
{
    namespace utils
    {
        /*********************************************************************
         * @brief 全局设置
         */
        template< typename _str >
        struct _is_str_t {};

        template<>
        struct _is_str_t< const char* > { using type_t = const char*; };

        template<>
        struct _is_str_t< const char[] > { using type_t = const char[]; };

        template<>
        struct _is_str_t< const std::string& > { using type_t = const std::string&; };

        /*********************************************************************
         * @brief 全局设置
         */
        class config_t
        {
        public:
            using json_t = hude::utils::json_t;

        public:
            static config_t& global();

            inline config_t& operator=( const json_t& init ) { root_ = init; return *this; }

            inline bool update( const char* path );

            inline std::string dump() const { return std::forward< std::string >( root_.dump() ); }

            inline json_t* operator->() { return &root_; }
            inline const json_t* operator->() const { return &root_; }

            inline json_t& operator*() { return root_; }
            inline const json_t& operator*() const { return root_; }

            inline json_t::reference operator[]( const json_t::object_t::key_type& key ) { return root_.at( key ); }
            inline json_t::const_reference operator[]( const json_t::object_t::key_type& key ) const { return root_.at( key ); }

            template< typename ... _str >
            inline hude::optional_t< json_t::const_iterator > path( _str&& ... args ) const;
            template< typename ... _str >
            inline hude::optional_t< json_t::iterator > path( _str&& ... args );

            template< typename _value, typename ... _str >
            inline _value get_or_default( const _value& def, _str&& ... args ) const;

        private:
            config_t() {}
            ~config_t() {}

            config_t( const config_t& ) = delete;
            config_t& operator=( const config_t& ) = delete;
        private:
            json_t root_;

        };

        /*********************************************************************
         * @brief 按给定文件更新设置，该更新行为应用文件中的所有设置项对当前设置进行局部更新，
         *          也就是保留当前设置存在而文件中缺少的设置项。
         */
        inline bool config_t::update( const char* path )
        {
            std::string content;

            {
                auto fp = fopen( path, "rb" );
                if( ! fp )
                {
                    log_err( "<config_t> error: open settings file %s", path );
                    return false;
                }

                fseek( fp, 0, SEEK_END );

                auto siz = ftell( fp );

                content.resize( siz );

                rewind( fp );

                int r = fread( &(content[0]), sizeof(char), siz, fp );

                fclose( fp );

                if( r < 0 && r != (int)siz )
                {
                    log_err( "<config_t> error: read settings file size: %d", r );
                    return false;
                }
            }

            auto change = json_t::parse( content.c_str() );

            root_.merge_patch( change );

            return true;
        }

        /*********************************************************************
         * @brief 获取全局设置
         */
        inline config_t& config_t::global()
        {
            static config_t g;

            return g;
        }

        /*********************************************************************
         * @brief 取指定json路径的json_t迭代器
         */
        template< typename ... _str >
        inline hude::optional_t< config_t::json_t::const_iterator > config_t::path( _str&& ... args ) const
        {
            return json_path_t::_path( root_, { std::forward< _str >( args ) ... } );
        }

        /*********************************************************************
         * @brief 取指定json路径的json_t迭代器
         */
        template< typename ... _str >
        inline hude::optional_t< config_t::json_t::iterator > config_t::path( _str&& ... args )
        {
            return json_path_t::_path( root_, { std::forward< _str >( args ) ... } );
        }

        /*********************************************************************
         * @brief 取指定json路径的值，如果不存在则指定默认值
         */
        template< typename _value, typename ... _str >
        inline _value config_t::get_or_default( const _value& def, _str&& ... args ) const
        {
            auto itr = json_path_t::_path( root_, { std::forward< _str >( args ) ... } );
            return itr? (*itr)->template get< _value >() : def;
        }
    } //namespace utils
} //namespace arg

#endif //__config_dkfjiwoo3w3yy82389__

